package com.pubinfo.passbook.engine.chain.transfer;

import com.pubinfo.passbook.common.model.http.engine.ComputeParamSlot;
import com.pubinfo.passbook.engine.cell.ComputeUnit;
import com.pubinfo.passbook.engine.chain.ComputeChain;
import com.pubinfo.passbook.engine.constants.ComputeUnitType;
import com.pubinfo.passbook.engine.process.ParamenterProcessor;

import java.util.Arrays;
import java.util.Collection;

/**
 * 计算链转化器
 * 算是计算单元的一种
 *
 * @param <T> 原本计算链的处理数据类型
 * @param <S> 目标计算单元处理的数据类型
 * @param <R> 返回值（数值计算或者..）
 */
public abstract class ComputeChainTransfer<T, S, R> extends ComputeUnit<T, R> {

    protected ComputeChain<S, R> realComputeChain;

    public ComputeChainTransfer(ComputeChain<S, R> computor) {
        realComputeChain = computor;
    }

    /**
     * 默认实现，如有需要请覆盖
     *
     * @param data
     * @param result
     * @return
     */
    @Override
    public R compute(T data, R result) {
        // 继承父计算链的缓存
        realComputeChain.setCache(cache);
        return realComputeChain.compute(convert(data), result);
    }

    /**
     * 核心方法：如何将不兼容的类型转化为兼容的类型
     *
     * @param data
     * @return
     */
    abstract S convert(T data);

    /**
     * 计算链肯定是一个单向的计算，不会是其他类型。
     *
     * @return
     */
    @Override
    public String getUnitType() {
        return ComputeUnitType.SINGLE;
    }

    /**
     * 本质这个计算单元是对计算链的包装，这个计算单元的一部分操作也就失去了意义
     * <p>
     * 计算链内部计算单元的所有参数会在初始化时就被完全封装完成。
     *
     * @param processors
     */
    @Override
    public void loadProcessors(Collection<? extends ParamenterProcessor<?, ?>> processors) {
    }


    @Override
    public Collection<ComputeParamSlot> getParamSlots() {
        return Arrays.asList();
    }
}
